package com.zwy.tree;

import com.zwy.linear.Node;

import javax.crypto.spec.RC2ParameterSpec;

public class BinTreeNode implements Node {
    private Object data;  // the data
    private BinTreeNode parent; //the parent node
    private BinTreeNode lChild; //
    private BinTreeNode rChild;
    private int height;    //以该节点为根的子树的高度
    private int size;// 该节点的子孙数

    public BinTreeNode() {
    }
    //初始化数据
    public BinTreeNode(Object data) {
        this.data = data;
        height=0;
        size=1;
        parent=lChild=rChild=null;
    }


/**************  Node 接口 方法 ********************/
    @Override
    public Object getData() {
        return data;
    }

    @Override
    public void setData(Object obj) {
        this.data=obj;
    }

    /************ 辅助方法，判断当前节点的位置情况  **************/
    //判断是否有父亲
    public boolean hasParent(){
        return parent!=null;
    }
    //判断是否有左孩子
    public boolean hasLChild(){
        return lChild!=null;
    }
    //判断是否有右孩子
    public boolean hasRChild(){
        return rChild!=null;
    }
    //判断是否为叶子节点
    public boolean isLeaf(){
        return !hasLChild()&&!hasRChild();
    }
    //判断是否为某节点的左孩子
    public boolean isLChild(){
        return (hasParent()&&this==parent.lChild);
    }
    //判断是否为某节点的右孩子
    public boolean isRChild(){
        return (hasParent()&&this==parent.rChild);
    }



    /************** 与Height有关的方法 **********/
    public int getHeight(){
        return  height;
    }
    //更新当前节点机器祖先的高度
    public void updateHeight(){
        int newH=0;  //初始化为0
        if(hasLChild())newH=Math.max(newH,1+getLChild().getHeight());
        if(hasRChild())newH=Math.max(newH,1+getRChild().getHeight());
        if(newH==height)return;
        if(hasParent())getParent().updateHeight();//递归地更新祖先节点高度
    }

    /*************  与size相关的方法  *************/
    //取以该节点为根的树的节点数
    public int getSize(){
       return size;
    }

    //更新当前节点及其祖先的子孙数
    public void updateSize(){
        size=1; //初始化为1
        if(hasLChild())size+=getLChild().getSize();//加上左子树的数目
        if(hasRChild())size+=getRChild().getSize();//加上右子树的数目
        if(hasParent())getParent().updateSize();//递归更新祖先节点size
    }

    /********** 与Parent相关方法*********/
    //取父节点
    public BinTreeNode getParent(){
        return parent;
    }
    //断开与父亲的关系
    public void sever(){
        if(!hasParent())return;
        if(isLChild())parent.lChild=null;
        else parent.rChild=null;
        parent.updateHeight();//更新祖先高度
        parent.updateSize(); //更新祖先规模
        parent=null;
    }

    /********* 与lChild 有关的方法 **********/
    //取左孩子
    public BinTreeNode getLChild(){
        return  lChild;
    }
    //设置当前节点的左孩子，并返回原来的左孩子
    public BinTreeNode setLChild(BinTreeNode e){
        BinTreeNode oldLC=getLChild();
        if(hasLChild()){
            lChild.sever(); //断开当前左孩子与父亲的关系
        }
        if(e!=null){
            e.sever();
            this.lChild=e;
            e.parent=this;
            this.updateHeight();
            this.updateSize();
        }
        return oldLC;
    }


    /****************** 与rChild 有关的方法*********************/
    //取右孩子
    public BinTreeNode getRChild(){
        return rChild;
    }
    //设置当前节点的右孩子，并返回原右孩子
    public BinTreeNode setRChild(BinTreeNode rc){
        BinTreeNode oldRC=this.rChild;
        if(hasRChild()){
            rChild.sever();
        }
        if(rc!=null){
            rc.sever();
            this.rChild=rc;
            rc.parent=this;
            this.updateHeight();
            this.updateSize();
        }
        return oldRC;
    }







}
